#define GL_GLEXT_PROTOTYPES

#include <QFile>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Utils.h"
#include <qopenglframebufferobject.h>

#include "MyOpenGL.h"

void MyOpenGL::setUpVertices() {
	
	float verticesPoints[] = {
		1.0f, -1.0f, 0.0f,
		-1.0f, -1.0f, 0.0f,
		-1.0f,  1.0f, 0.0f,
		1.0f, -1.0f, 0.0f,
		-1.0f,  1.0f, 0.0f,
		1.0f,  1.0f, 0.0f,
	};

	static const GLfloat g_quad_texture_coords_buffer_data[] = {
	1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
	1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
	};

	glGenVertexArrays(1, vao);
	glBindVertexArray(vao[0]);
	glGenBuffers(2, vbo);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(verticesPoints), verticesPoints, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_texture_coords_buffer_data), g_quad_texture_coords_buffer_data, GL_STATIC_DRAW);

}



MyOpenGL::MyOpenGL(QWidget *parent)
	: QOpenGLWidget(parent)
{
	ui.setupUi(this);
}

MyOpenGL::~MyOpenGL()
{}

void MyOpenGL::paintGL()
{
	QOpenGLFramebufferObject* frame = new QOpenGLFramebufferObject(QSize(800, 600));
	frame->bind();
	glClear(GL_DEPTH_BUFFER_BIT);
	glClear(GL_COLOR_BUFFER_BIT);
	glClearColor(1, 0, 0, 1);
	
	glUseProgram(renderingProgram);

	mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
	projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");

	int w = this->width();
	int h = this->height();

	aspect = (float)w / (float)h;
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);

	vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-camera[0], -camera[1], -camera[2]));
	mMat = glm::translate(glm::mat4(1.0f), glm::vec3(cubeLoc[0], cubeLoc[1], cubeLoc[2]));
	mvMat = vMat * mMat;

	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));


	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);

	glActiveTexture(GL_TEXTURE0);
	texture->bind();

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CW);
	glDrawArrays(GL_TRIANGLES, 0, 6);
	frame->release();
	

	glClear(GL_DEPTH_BUFFER_BIT);
	glClear(GL_COLOR_BUFFER_BIT);
	glClearColor(0, 1, 0, 1);

	glUseProgram(renderingProgram);

	mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
	projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");



	aspect = (float)w / (float)h;
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);

	vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-camera[0], -camera[1], -camera[2]));
	mMat = glm::translate(glm::mat4(1.0f), glm::vec3(cubeLoc[0], cubeLoc[1], cubeLoc[2]));
	mvMat = vMat * mMat;

	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));


	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, frame->texture());

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CW);
	glDrawArrays(GL_TRIANGLES, 0, 6);
}

void MyOpenGL::resizeGL(int w, int h)
{
	glViewport(0, 0, w, h);
}

QByteArray ReadFile(QString file) {
	QFile f(file);
	bool r = f.open(QIODevice::ReadOnly);
	return f.readAll();
}

void MyOpenGL::initializeGL()
{
	glewInit();
	renderingProgram = UTILS::CreateShaderProgram(":/shaders/vshaderSource.txt", ":/shaders/fshaderSource.txt");
	camera[0] = 0;
	camera[1] = 0;
	camera[2] = 8;

	cubeLoc[0] = 0;
	cubeLoc[1] = -2;
	cubeLoc[2] = 0;

	setUpVertices();

	texture = new QOpenGLTexture(QImage("D:/ofdFiles/images/Lena_512x512.jpg").mirrored());
	texture->create();
}

